package com.furtherstar.auth.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.furtherstar.auth.controller.dto.CorpQuery;
import com.furtherstar.auth.controller.dto.DeptTree;
import com.furtherstar.auth.controller.dto.DeptUserQuery;
import com.furtherstar.auth.dao.enums.Disabled;
import com.furtherstar.auth.dao.mapper.CorpDeptMapper;
import com.furtherstar.auth.dao.mapper.CorpMapper;
import com.furtherstar.auth.dao.mapper.CorpWorkDeptMapper;
import com.furtherstar.auth.dao.mapper.CorpWorkMapper;
import com.furtherstar.auth.dao.model.Corp;
import com.furtherstar.auth.dao.model.CorpDept;
import com.furtherstar.auth.dao.model.CorpDeptExample;
import com.furtherstar.auth.dao.model.CorpDeptExample.Criteria;
import com.furtherstar.auth.dao.model.CorpExample;
import com.furtherstar.auth.dao.model.CorpWorkDeptExample;
import com.furtherstar.auth.dao.model.CorpWorkExample;
import com.furtherstar.auth.service.CorpDeptService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageSerializable;
import com.yummy.convention.collection.TreeUtils;
import com.yummy.convention.exception.AssertUtil;
import com.yummy.convention.lang.IDGenerator;
import com.yummy.security.User;
import com.yummy.web.context.RequestContext;
import com.yummy.web.security.bean.SimpleUser;

@Service
public class CorpDeptServiceImpl implements CorpDeptService{

	@Autowired
	private CorpMapper corpMapper;
	@Autowired
	private CorpDeptMapper corpDeptMapper;
	@Autowired
	private CorpWorkDeptMapper corpWorkDeptMapper;
	@Autowired
	private CorpWorkMapper corpWorkMapper;

	@Override
	public List<Corp> queryCorpList(CorpQuery corpQuery) {
		CorpExample example = new CorpExample();
		com.furtherstar.auth.dao.model.CorpExample.Criteria criteria = example.createCriteria();
		if(StringUtils.isNotBlank(corpQuery.getCorpName())) {
			criteria.andNameLike("%"+corpQuery.getCorpName()+"%");
		}
		List<Corp> list = corpMapper.selectByExample(example);
		if(list == null) {
			return Collections.emptyList();
		}
		return list;
	}

	@Override
	public List<Corp> getAvailableCorpList(CorpQuery corpQuery) {
		CorpExample example = new CorpExample();
		com.furtherstar.auth.dao.model.CorpExample.Criteria criteria = example.createCriteria()
				.andDisabledEqualTo(Disabled.normal.ordinal());
		if(StringUtils.isNotBlank(corpQuery.getCorpName())) {
			criteria.andNameLike("%"+corpQuery.getCorpName()+"%");
		}
		List<Corp> list = corpMapper.selectByExample(example);
		if(list == null) {
			return Collections.emptyList();
		}
		return list;
	}

	@Override
	public List<DeptTree> getAllCorpDeptTree() {
		List<CorpDept> list = corpDeptMapper.selectByExample(null);
		if(CollectionUtils.isEmpty(list)) {
			return Collections.emptyList();
		}
		List<DeptTree> trees = toDeptTree(list);
		return TreeUtils.toTree(trees, "id", "parentId", "sort", "children", DeptTree.class);
	}

	private List<DeptTree> toDeptTree(List<CorpDept> list) {
		List<DeptTree> trees = new ArrayList<>();
		for(CorpDept cd : list) {
			trees.add(toDeptTree(cd));
		}
		return trees;
	}

	private DeptTree toDeptTree(CorpDept cd) {
		DeptTree t = new DeptTree();
		t.setCorpId(cd.getCorpId());
		t.setDisabled(cd.getDisabled());
		t.setId(cd.getId());;
		t.setName(cd.getName());
		t.setParentId(cd.getParentId());
		t.setSort(cd.getSort());
		return t;
	}

	@Override
	public List<DeptTree> getAvailableCorpDeptTree(Long corpId) {
		CorpDeptExample example = new CorpDeptExample();
		example.createCriteria().andCorpIdEqualTo(corpId)
			.andDisabledEqualTo(Disabled.normal.ordinal());
		List<CorpDept> list = corpDeptMapper.selectByExample(example);
		if(list == null) {
			return null;
		}
		List<DeptTree> trees = toDeptTree(list);
		return TreeUtils.toTree(trees, "id", "parentId", "sort", "children", DeptTree.class);
	}

	@Override
	public List<DeptTree> getCorpDeptTree(Long corpId) {
		CorpDeptExample example = new CorpDeptExample();
		example.createCriteria().andCorpIdEqualTo(corpId);
		List<CorpDept> list = corpDeptMapper.selectByExample(example);
		if(list == null) {
			return null;
		}
		List<DeptTree> trees = toDeptTree(list);
		return TreeUtils.toTree(trees, "id", "parentId", "sort", "children", DeptTree.class);
	}

	@Override
	public CorpDept getDept(Long deptId) {
		return corpDeptMapper.selectByPrimaryKey(deptId);
	}

	@Override
	public Long add(CorpDept dept) {
		AssertUtil.isTrue(!exist(dept),"同级部门名称不可重复");
		createMark(dept);
		corpDeptMapper.insert(dept);
		return dept.getId();
	}

	private void createMark(CorpDept dept) {
		dept.setId(IDGenerator.getId());
		dept.setDisabled(Disabled.normal.ordinal());
		User user = RequestContext.getCurrentUser();
		dept.setLmNickname(user.getNickname());
		dept.setLmUserid((Long) user.getUserid());
		dept.setLmTime(new Date());
	}

	private boolean exist(CorpDept dept) {
		CorpDeptExample example = new CorpDeptExample();
		Criteria criteria = example.createCriteria().andParentIdEqualTo(dept.getParentId())
			.andNameEqualTo(dept.getName());
		if(dept.getId() != null) {
			criteria.andIdNotEqualTo(dept.getId());
		}
		return corpDeptMapper.countByExample(example) != 0;
	}

	@Override
	public Long update(CorpDept dept) {
		AssertUtil.isTrue(!exist(dept),"同级部门名称不可重复");
		optMark(dept);
		corpDeptMapper.updateByPrimaryKeySelective(dept);
		return dept.getId();
	}

	private void optMark(CorpDept dept) {
		User user = RequestContext.getCurrentUser();
		dept.setLmNickname(user.getNickname());
		dept.setLmUserid((Long) user.getUserid());
		dept.setLmTime(new Date());
	}

	@Override
	public Long enable(Long deptId) {
		CorpDept dept = new CorpDept();
		dept.setId(deptId);
		dept.setDisabled(Disabled.normal.ordinal());
		optMark(dept);
		int row = corpDeptMapper.updateByPrimaryKeySelective(dept);
		AssertUtil.isTrue(row == 1,"找不到记录");
		return deptId;
	}

	@Override
	public Long disable(Long deptId) {
		CorpDept dept = new CorpDept();
		dept.setId(deptId);
		dept.setDisabled(Disabled.disabled.ordinal());
		optMark(dept);
		int row = corpDeptMapper.updateByPrimaryKeySelective(dept);
		AssertUtil.isTrue(row == 1,"找不到记录");
		return deptId;
	}

	@Override
	@Transactional
	public Boolean delete(Long deptId) {
		AssertUtil.isTrue(canDelete(deptId),"包含子级部门不可删除");
		int row = corpDeptMapper.deleteByPrimaryKey(deptId);
		AssertUtil.notNull(row == 1,"找不到记录");
		deleteRelated(deptId);
		return true;
	}

	private boolean canDelete(Long deptId) {
		CorpDeptExample example = new CorpDeptExample();
		example.createCriteria().andParentIdEqualTo(deptId);
		return corpDeptMapper.countByExample(example) == 0;
	}

	private void deleteRelated(Long deptId) {
		CorpWorkDeptExample example = new CorpWorkDeptExample();
		example.createCriteria().andDeptIdEqualTo(deptId);
		corpWorkDeptMapper.deleteByExample(example);
	}

	@Override
	public PageSerializable<SimpleUser> queryDeptUsers(DeptUserQuery deptUserQuery) {
		PageHelper.startPage(deptUserQuery.getPageNum(), deptUserQuery.getPageSize());
		return PageSerializable.of(corpWorkDeptMapper.queryDistinctUsers(deptUserQuery));
	}

	@Override
	public Long addCorp(Corp corp) {
		AssertUtil.isTrue(!exist(corp),"已存在");
		createMark(corp);
		corpMapper.insert(corp);
		return corp.getId();
	}

	private void createMark(Corp corp) {
		corp.setId(IDGenerator.getId());
		corp.setDisabled(Disabled.normal.ordinal());
		User user = RequestContext.getCurrentUser();
		corp.setLmNickname(user.getNickname());
		corp.setLmTime(new Date());
		corp.setLmUserid((Long) user.getUserid());
	}

	private boolean exist(Corp corp) {
		CorpExample example = new CorpExample();
		com.furtherstar.auth.dao.model.CorpExample.Criteria criteria = example.createCriteria().andNameEqualTo(corp.getName());
		if(corp.getId() != null) {
			criteria.andIdNotEqualTo(corp.getId());
		}
		return corpMapper.countByExample(example) != 0;
	}

	@Override
	public Long updateCorp(Corp corp) {
		AssertUtil.isTrue(!exist(corp),"已存在");
		optMark(corp);
		corpMapper.updateByPrimaryKeySelective(corp);
		return corp.getId();
	}

	private void optMark(Corp corp) {
		User user = RequestContext.getCurrentUser();
		corp.setLmNickname(user.getNickname());
		corp.setLmTime(new Date());
		corp.setLmUserid((Long) user.getUserid());
	}

	@Override
	public Long enableCorp(Long corpId) {
		Corp corp = new Corp();
		corp.setId(corpId);
		corp.setDisabled(Disabled.normal.ordinal());
		optMark(corp);
		corpMapper.updateByPrimaryKeySelective(corp);
		return corpId;
	}

	@Override
	public Long disableCorp(Long corpId) {
		Corp corp = new Corp();
		corp.setId(corpId);
		corp.setDisabled(Disabled.disabled.ordinal());
		optMark(corp);
		corpMapper.updateByPrimaryKeySelective(corp);
		return corpId;
	}

	@Override
	@Transactional
	public Boolean deleteCorp(Long corpId) {
		AssertUtil.isTrue(canDeleteCorp(corpId),"包含子级部门不可删除");
		int row = corpMapper.deleteByPrimaryKey(corpId);
		AssertUtil.notNull(row == 1,"找不到记录");
		deleteCorpRelated(corpId);
		return true;
	}

	private void deleteCorpRelated(Long corpId) {
		CorpWorkExample example = new CorpWorkExample();
		example.createCriteria().andCorpIdEqualTo(corpId);
		corpWorkMapper.deleteByExample(example);
	}

	private boolean canDeleteCorp(Long corpId) {
		CorpDeptExample example = new CorpDeptExample();
		example.createCriteria().andCorpIdEqualTo(corpId);
		return corpDeptMapper.countByExample(example) == 0;
	}

}
